//ctors

inline GreatUInt::GreatUInt(const UInt i_num)
{
	Assign(i_num);
}

inline GreatUInt::GreatUInt(const char* i_string)
{
	Assign(i_string);
}

inline GreatUInt::GreatUInt(const std::string& i_string)
{
	Assign(i_string);
}

inline GreatUInt::GreatUInt( const FastUInt& i_that )
{
	Assign(i_that);
}

inline GreatUInt::GreatUInt(const GreatUInt& i_that)
:m_data(i_that.m_data)
{
}

inline GreatUInt& GreatUInt::operator=(const GreatUInt& i_that)
{
	m_data = i_that.m_data;
	return *this;
}

inline GreatUInt& GreatUInt::operator=(const UInt i_num)
{
	return Assign(i_num);
}

//accessors

inline UInt GreatUInt::ToUInt() const
{
	if(m_data.size() == 1)
		return m_data[0];

	return m_data[1] * MAX_ELEMENT_VALUE + m_data[0];
}

inline bool GreatUInt::IsZero() const
{
	return (m_data.size()==1) && (m_data.at(0)==0);
}

inline bool GreatUInt::IsInvalid() const
{
	return (m_data.size()==1) && (m_data.at(0)==MAX_UINT);
}

inline bool GreatUInt::IsUInt() const
{
	return (m_data.size() == 1) || operator<=(*this, GreatUInt(MAX_UINT));
}

//modifiers

inline GreatUInt& GreatUInt::Assign(const UInt i_num)
{
	m_data.clear();

	if(i_num<MAX_ELEMENT_VALUE){
		m_data.push_back(i_num);
	}else{
		const UInt value = i_num%MAX_ELEMENT_VALUE;
		const UInt report = i_num/MAX_ELEMENT_VALUE;
		m_data.push_back(value);
		m_data.push_back(report);
	}
	return *this;
}

inline GreatUInt& GreatUInt::Assign(const char* i_string)
{
	if(i_string)
		return Assign(std::string(i_string));

	return SetZero();
}

inline GreatUInt& GreatUInt::SetZero()
{
	m_data.clear();
	m_data.push_back(0);
	return *this;
}

inline GreatUInt& GreatUInt::SetOne()
{
	m_data.clear();
	m_data.push_back(1);
	return *this;
}

inline GreatUInt& GreatUInt::SetInvalid()
{
	m_data.clear();
	m_data.push_back(MAX_UINT);
	return *this;
}

inline GreatUInt GreatUInt::operator++(int)
{
	GreatUInt temp(*this);
	++*this;
	return temp;
}

inline GreatUInt GreatUInt::operator--(int)
{
	GreatUInt temp(*this);
	--*this;
	return temp;
}

inline GreatUInt& GreatUInt::operator/=(const GreatUInt& i_that)
{
	return DivWithRem(*this, i_that);
}

inline GreatUInt& GreatUInt::operator%=(const GreatUInt& i_that)
{
	return DivWithRem(*this, i_that, false);
}

inline GreatUInt& GreatUInt::Add(const GreatUInt& i_first, const GreatUInt& i_second)
{
	return operator=(i_first).operator+=(i_second);
}

inline GreatUInt& GreatUInt::Sub(const GreatUInt& i_first, const GreatUInt& i_second)
{
	return operator=(i_first).operator-=(i_second);
}

inline GreatUInt& GreatUInt::Mul(const GreatUInt& i_first, const GreatUInt& i_second)
{
	return operator=(i_first).operator*=(i_second);
}

inline GreatUInt& GreatUInt::BitAnd(const GreatUInt& i_first, const GreatUInt& i_second)
{
	return operator=(i_first).operator&=(i_second);
}

inline GreatUInt& GreatUInt::BitOr(const GreatUInt& i_first, const GreatUInt& i_second)
{
	return operator=(i_first).operator|=(i_second);
}

inline GreatUInt& GreatUInt::BitXor(const GreatUInt& i_first, const GreatUInt& i_second)
{
	return operator=(i_first).operator^=(i_second);
}

inline void GreatUInt::Swap(GreatUInt& i_that)
{
	m_data.swap(i_that.m_data);
}


// non members

inline const GreatUInt operator+(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp+=i_right;
	return temp;
}
inline const GreatUInt operator*(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp*=i_right;
	return temp;
}

inline const GreatUInt operator*(const GreatUInt& i_greatUInt, UInt i_factor)
{
	GreatUInt temp(i_greatUInt);
	temp*=i_factor;
	return temp;
}

inline const GreatUInt operator*(UInt i_factor, const GreatUInt& i_greatUInt)
{
	GreatUInt temp(i_greatUInt);
	temp*=i_factor;
	return temp;
}

inline const GreatUInt operator/(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp*=i_right;
	return temp;
}

inline UInt operator%(const GreatUInt& i_greatUInt, UInt i_factor)
{
	GreatUInt temp(i_greatUInt);
	temp/=GreatUInt(i_factor);
	temp*=i_factor;
	UInt diff = i_greatUInt.m_data[0] - temp.m_data[0];
	if(temp.m_data.size() > 1)
		diff += (i_greatUInt.m_data[1] - temp.m_data[1]) * GreatUInt::MAX_ELEMENT_VALUE;
	return diff;
}

inline const GreatUInt operator%(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp%=i_right;
	return temp;
}

inline const GreatUInt operator&(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp&=i_right;
	return temp;

}

inline const GreatUInt operator|(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp|=i_right;
	return temp;
}

inline const GreatUInt operator^(const GreatUInt& i_left, const GreatUInt& i_right)
{
	GreatUInt temp(i_left);
	temp^=i_right;
	return temp;
}

inline bool operator<(const GreatUInt& i_left, const GreatUInt& i_right)
{
	return i_left.IsLessThan(i_right);
}

inline bool operator<=(const GreatUInt& i_left, const GreatUInt& i_right)
{
	return !i_right.IsLessThan(i_left);
}

inline bool operator>(const GreatUInt& i_left, const GreatUInt& i_right)
{
	return i_right.IsLessThan(i_left);
}

inline bool operator>=(const GreatUInt& i_left, const GreatUInt& i_right)
{
	return !i_left.IsLessThan(i_right);
}

inline bool operator!=(const GreatUInt& i_left, const GreatUInt& i_right)
{
	return !(i_left==i_right);
}

inline bool operator==(const GreatUInt& i_left, const GreatUInt& i_right)
{
	return i_left.m_data == i_right.m_data;
}

inline const GreatUInt Exp( const GreatUInt& i_base, const UInt i_exp )
{
	GreatUInt temp(i_base);
	return temp.ApplyExp(i_exp);
}

